package fr.fermeManager.application.views.utils;

import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.RowFilter;

import fr.fermeManager.application.utils.EnumEtat;
import fr.fermeManager.application.views.models.ModelGridTransactions;
import fr.fermeManager.library.model.beans.Transaction;
import fr.fermeManager.library.model.beans.TypeTransaction;

public class FilterGridTransactions extends RowFilter<ModelGridTransactions, Integer> {
	
	private EnumEtat etat;
	
	private TypeTransaction typeTransaction;
	
	private boolean inclureSousTypes = false;
	
	private String chaineARechercher;
	
	private Integer montantMax;
	
	private Integer montantMin;
	
	private Date dateDebut;
	
	private Date dateFin;
	
	private List<TypeTransaction> listeTypes;
	
	public FilterGridTransactions(EnumEtat etat, TypeTransaction valTypeTransaction,List<TypeTransaction> listeTypesParam, boolean inclureSousTypesParam, String chaineARechercher, Integer montantMax, Integer montantMin, Date dateDebut, Date dateFin) {
		super();
		setEtat(etat);
		setTypeTransaction(valTypeTransaction);
		setChaineARechercher(chaineARechercher);
		setMontantMax(montantMax);
		setMontantMin(montantMin);
		setDateDebut(dateDebut);
		setDateFin(dateFin);
		setInclureSousTypes(inclureSousTypesParam);
		setListeTypes(listeTypesParam);
	}



	@Override
	public boolean include(@SuppressWarnings("rawtypes") Entry entry) {
		
		ModelGridTransactions dataListModel = (ModelGridTransactions) entry.getModel();
		Transaction transc = dataListModel.getElementByIndex((Integer) entry.getIdentifier());
		
		if(etat == EnumEtat.Actifs){
			if(!transc.isActif())
				return false;
		}
		if(etat == EnumEtat.Inactifs){
			if(transc.isActif())
				return false;
		}
		
		if(typeTransaction!=null){
			if(!inclureSousTypes){
				if(transc.getTypeTransaction().getId() != typeTransaction.getId()){
					return false;
				}
			}else{
				if(!estSousFils(transc.getTypeTransaction(),typeTransaction,listeTypes)){
					return false;
				}
			}
		}
		
		if(chaineARechercher!=null){
			
			String sansAccent = Normalizer.normalize(chaineARechercher, Normalizer.Form.NFD).replaceAll("[\u0300-\u036F]", "");
			sansAccent = sansAccent.toUpperCase();
			
			if((transc.getLibelle()==null) && (transc.getDescription()==null)){
				return false;
			}
			if(transc.getLibelle()==null){
				if(!transc.getDescription().toUpperCase().matches(".*"+sansAccent+".*")){
					return false;
				}
			}
			if(transc.getDescription()==null){
				if(!transc.getLibelle().toUpperCase().matches(".*"+sansAccent.toLowerCase()+".*")){
					return false;
				}
			}
			if((transc.getLibelle()!=null)&&(transc.getDescription()!=null)){
				if(!transc.getLibelle().toUpperCase().matches(".*"+sansAccent.toLowerCase()+".*")){
						if(!transc.getDescription().toUpperCase().matches(".*"+sansAccent+".*")){
							return false;
						}
				}
			}
		}
		
		if(montantMax!=null){
			if(transc.getMontant()>montantMax){
				return false;
			}
		}
		
		if(montantMin!=null){
			if(transc.getMontant()<montantMin){
				return false;
			}
		}
		
		if(dateDebut!=null){
			if(dateDebut.after(transc.getDateCreation().getTime())){
				return false;
			}
		}
		
		if(dateFin!=null){
			if(dateFin.before(transc.getDateCreation().getTime())){
				return false;
			}
		}
		
		return true;
	}



	private boolean estSousFils(TypeTransaction sourceParam, TypeTransaction targetParam, List<TypeTransaction> listeTypesParam) {
		if(sourceParam.getId() == targetParam.getId()){
			return true;
		} else{
			if(sourceParam.getIdParent() == targetParam.getId()){
				return true;
			}else{
				List<TypeTransaction> listeFilsTarget = new ArrayList<TypeTransaction>();
				for (TypeTransaction typeTransactionBoucle : listeTypesParam) {
					if(typeTransactionBoucle.getIdParent()!=null) {
						if(typeTransactionBoucle.getIdParent() == targetParam.getId()){
							listeFilsTarget.add(typeTransactionBoucle);
						}
						// Liste des enfants OK
						for (TypeTransaction enfantTmp : listeFilsTarget) {
							if(estSousFils(sourceParam,enfantTmp,listeTypesParam)){
								return true;
							}
						}
					}
				}
			}
		}
		return false;
	}



	/**
	 * @return the etat
	 */
	public EnumEtat getEtat() {
		return etat;
	}



	/**
	 * @param etat the etat to set
	 */
	public void setEtat(EnumEtat etat) {
		this.etat = etat;
	}



	/**
	 * @return the typeTransaction
	 */
	public TypeTransaction getTypeTransaction() {
		return typeTransaction;
	}



	/**
	 * @param typeTransaction the typeTransaction to set
	 */
	public void setTypeTransaction(TypeTransaction typeTransaction) {
		this.typeTransaction = typeTransaction;
	}



	/**
	 * @return the chaineARechercher
	 */
	public String getChaineARechercher() {
		return chaineARechercher;
	}



	/**
	 * @param chaineARechercher the chaineARechercher to set
	 */
	public void setChaineARechercher(String chaineARechercher) {
		this.chaineARechercher = chaineARechercher;
	}



	/**
	 * @return the montantMax
	 */
	public Integer getMontantMax() {
		return montantMax;
	}



	/**
	 * @param montantMax the montantMax to set
	 */
	public void setMontantMax(Integer montantMax) {
		this.montantMax = montantMax;
	}



	/**
	 * @return the montantMin
	 */
	public Integer getMontantMin() {
		return montantMin;
	}



	/**
	 * @param montantMin the montantMin to set
	 */
	public void setMontantMin(Integer montantMin) {
		this.montantMin = montantMin;
	}



	/**
	 * @return the dateDebut
	 */
	public Date getDateDebut() {
		return dateDebut;
	}



	/**
	 * @param dateDebut the dateDebut to set
	 */
	public void setDateDebut(Date dateDebut) {
		this.dateDebut = dateDebut;
	}



	/**
	 * @return the dateFin
	 */
	public Date getDateFin() {
		return dateFin;
	}



	/**
	 * @param dateFin the dateFin to set
	 */
	public void setDateFin(Date dateFin) {
		this.dateFin = dateFin;
	}



	/**
	 * @return the inclureSousTypes
	 */
	public boolean isInclureSousTypes() {
		return inclureSousTypes;
	}



	/**
	 * @param inclureSousTypes the inclureSousTypes to set
	 */
	public void setInclureSousTypes(boolean inclureSousTypes) {
		this.inclureSousTypes = inclureSousTypes;
	}



	/**
	 * @return the listeTypes
	 */
	public List<TypeTransaction> getListeTypes() {
		return listeTypes;
	}



	/**
	 * @param listeTypes the listeTypes to set
	 */
	public void setListeTypes(List<TypeTransaction> listeTypes) {
		this.listeTypes = listeTypes;
	}




}
